﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;

using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.media;
using umbraco.DataLayer;
using umbraco.editorControls;
using umbraco;
using System.Xml.Linq;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic;
using System.Xml.XPath;
using System.Configuration;

namespace DigibizAdvancedMediaPicker
{
    public class DAMP_ApplicationBase : ApplicationBase
    {
        protected static ISqlHelper SqlHelper
        {
            get { return umbraco.BusinessLogic.Application.SqlHelper; }
        }

        public DAMP_ApplicationBase()
        {
            Media.BeforeSave += Media_BeforeSave;
            Media.AfterSave += new Media.SaveEventHandler(Media_AfterSave);
            Media.BeforeDelete += new Media.DeleteEventHandler(Media_BeforeDelete);
        }

        #region Events

        protected void Media_BeforeSave(Media sender, SaveEventArgs e)
        {
            try
            {
                if (ConfigurationManager.AppSettings["DAMP_CallImageCropper"] != null && ConfigurationManager.AppSettings["DAMP_OnlyIfEmpty"] != null && Convert.ToBoolean(ConfigurationManager.AppSettings["DAMP_CallImageCropper"]))
                {
                    bool? savedImageCropper = (bool?)HttpContext.Current.Items["CallImagecropper-" + sender.Id];

                    if (savedImageCropper.HasValue && savedImageCropper.Value == true)
                    {
                        DAMP_Helper.CallImagecropper(sender, Convert.ToBoolean(ConfigurationManager.AppSettings["DAMP_OnlyIfEmpty"]));
                    }
                }
            }
            catch (Exception ex)
            {
                DAMP_Helper.LogException(ex);
            }
        }

        protected void Media_AfterSave(Media sender, umbraco.cms.businesslogic.SaveEventArgs e)
        {
            try
            {
                if (ConfigurationManager.AppSettings["DAMP_CallImageCropper"] != null && ConfigurationManager.AppSettings["DAMP_OnlyIfEmpty"] != null && Convert.ToBoolean(ConfigurationManager.AppSettings["DAMP_CallImageCropper"]))
                {
                    bool? savedImageCropper = (bool?)HttpContext.Current.Items["CallImagecropper-" + sender.Id];

                    if (!savedImageCropper.HasValue || (savedImageCropper.HasValue && savedImageCropper.Value == false))
                    {
                        //Call the save method again of the media object. Be careful that this code is only called once, because it will trigger the after save method again which could cause an infinite loop.
                        HttpContext.Current.Items["CallImagecropper-" + sender.Id] = true;
                        sender.Save();
                    }
                }
            }
            catch (Exception ex)
            {
                DAMP_Helper.LogException(ex);
            }

            UpdateDAMP(sender, false);
        }

        protected void Media_BeforeDelete(Media sender, umbraco.cms.businesslogic.DeleteEventArgs e)
        {
            UpdateDAMP(sender, true);
        }

        #endregion

        #region Other - Methods

        /// <summary>
        /// Update the mediaItem element inside the DAMP xml if a media file is updated.
        /// </summary>
        /// <param name="media"></param>
        /// <param name="deleteMediaItem"></param>
        private static void UpdateDAMP(Media media, bool deleteMediaItem)
        {
            try
            {
                ContentType contentType = media.ContentType;
                
                //This sql get's all the newest versions of the documents which store the DAMP xml and contain the id of the current media item.
                string sql = string.Format(@"
                select cpd.contentNodeId as nodeId, cpd.dataNText as xmlValue, cpt.Alias as propertyAlias from cmsDocument cd
	                inner join cmsPropertyData cpd ON cd.nodeId = cpd.contentNodeId
	                inner join cmsPropertyType cpt ON cpd.propertytypeid = cpt.id
                where cd.newest = 1
                and cd.versionId = cpd.versionId
                and cpd.dataNtext like '<DAMP fullMedia="""">%'
				and cpd.dataNtext like '%{0}%'", media.Id);

                List<DAMP_UpdateDocument> updateDocuments = new List<DAMP_UpdateDocument>();

                using (IRecordsReader dr = SqlHelper.ExecuteReader(sql))
                {
                    while (dr.Read())
                    {
                        try
                        {
                            //Get the documents which need to be updated.
                            updateDocuments.AddRange(DAMP_Helper.GetUpdateDocuments(dr.GetString("xmlValue"), dr.GetInt("nodeId"), dr.GetString("propertyAlias"), media.Id));
                        }
                        catch (Exception ex)
                        {
                            //If the xml can't be converted log it and go to the next row.
                            DAMP_Helper.LogException(ex);
                        }
                    }
                }

                foreach (DAMP_UpdateDocument updateDocument in updateDocuments)
                {
                    try
                    {
                        //Update the DAMP xml with the updated media item.
                        DAMP_Helper.UpdateDAMPXml(updateDocument.XmlDocument, media.Id, deleteMediaItem);

                        //Update the document with the new DAMP xml.
                        Document document = new Document(updateDocument.Id);
                        document.getProperty(updateDocument.Alias).Value = updateDocument.XmlDocument.ToString();

                        if (document.Published)
                        {
                            umbraco.BusinessLogic.User user = umbraco.BusinessLogic.User.GetCurrent();

                            if (user == null)
                            {
                                //If no user is found use the admin.
                                user = new umbraco.BusinessLogic.User(0);
                            }

                            //If the document is published publish it again so the new xml becomes available inside the umbraco xml (umbraco.config).
                            document.Publish(user);
                            umbraco.library.UpdateDocumentCache(document.Id);
                        }
                    }
                    catch (Exception ex)
                    {
                        //If the Document can't be updated log it and go to the next row.
                        DAMP_Helper.LogException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                DAMP_Helper.LogException(ex);
            }
        }

        #endregion
    }
}